package contegor.scire.core.queries;

import java.util.Comparator;

import contegor.scire.core.Connectable;
import contegor.scire.core.Id;
import contegor.scire.core.IdFragment;
import contegor.scire.core.Identifiable;
import contegor.scire.core.Link;

/**
 * This {@link Condition} filters {@link Connectable}s and let them pass if they are connected with at least
 * one {@link Identifiable} who's {@link Id} has the same root as the one given, and its last element
 * is of the same {@link IdFragment} type but with greater value, as defined by its {@link Comparator}.
 * Also allows nesting other {@link Condition}s that are applied to the {@link Link} between
 * the {@link Connectable} and the {@link Identifiable}, if such {@link Link} exists.
 *
 * @version $Revision$
 * @author  Héctor Cirbián Pousa ($Author$)
 */
public class IsConnectedWithGreaterThan<C extends Connectable> extends TargetNestCondition<C> {
  private static final long serialVersionUID = -5759156985084406578L;

  /** 
   * Creates a {@link Condition} that filters {@link Connectable}s and lets them pass if they are source of at 
   * least one {@link Link} who's target {@link Id} is 'greater' than the {@link Id} given.
   */
  public IsConnectedWithGreaterThan(Id target) {
    super(target);
  }

  /** 
   * Creates a {@link Condition} that filters {@link Connectable}s and lets them pass if they are source of at 
   * least one {@link Link} who's target {@link Id} is 'greater' than the {@link Id} given.
   * The {@link Link} in between must also fulfill the nested {@link Condition}.
   * The {@link Condition#eval(Connectable)} method will do a logic <code>and</code> between the two checks.
   * It is granted that the main condition will be evaluated first and, if it is true, the nested will be evaluated. 
   */
  public IsConnectedWithGreaterThan(Id target, Condition<Link> nested) {
    super(target, nested);
  }

  protected Link getLinkFulfillsCondition(C source) {
    Link link = source.getCeilLink(this.target);
    if ((link != null) && 
        (this.target.getParentId().equals(link.getTarget().getParentId())) &&
        (this.target.getLastIdFragment().getClass().equals(link.getTarget().getLastIdFragment().getClass())))
      return link;
    else
      return null;
  };

  @Override
  public IsConnectedWithGreaterThan<C> clone() {
    // Id is immutable.
    if (this.nested == null)
      return new IsConnectedWithGreaterThan<C>(this.target);
    else
      return new IsConnectedWithGreaterThan<C>(this.target, this.nested.clone());
  }
}
